Return to start page

Systems/World/Struct Spawn Point.j

Code

		
1			library AStructSystemsWorldSpawnPoint requires optional ALibraryCoreDebugMisc, ALibraryCoreGeneralPlayer, ALibraryCoreMathsPoint, ALibraryCoreStringConversion, AStructCoreGeneralHashTable
2
3 /// @struct ASpawnPoint provides the functionality of common creep spawn points, mostly used in RPG maps.
4 struct ASpawnPoint
5 //static start members
6 private static real m_time
7 private static string m_effectPath
8 private static integer m_dropChance
9 private static boolean m_distributeItems
10 private static player m_owner
11 private static string m_textDistributeItem
12 //static member
13 private static integer m_dropOwnerId
14 //dynamic members
15 private integer m_count
16 //start members
17 private real m_x
18 private real m_y
19 private real m_range
20 //members
21 private unitpool m_unitPool
22 private itempool m_itemPool
23 private trigger m_deathTrigger
24 private timer m_spawnTimer
25 private group m_unitGroup
26
27 //! runtextmacro optional A_STRUCT_DEBUG("\"ASpawnPoint\"")
28
29 //dynamic members
30
31 public method setCount takes integer count returns nothing
32 set this.m_count = count
33 endmethod
34
35 public method count takes nothing returns integer
36 return this.m_count
37 endmethod
38
39 //convenience methods
40
41 public method addExistingUnit takes unit existingUnit returns integer
42 local integer id = this.m_count
43 call GroupAddUnit(this.m_unitGroup, existingUnit)
44 set this.m_count = id + 1
45 return id
46 endmethod
47
48 /// Note that after unit @param existingUnit has died there will be spawned a new RANDOM unit from unit pool.
49 /// @param weight Weight of added unit type. This value has no effects if @param addType is false.
50 /// @return Returns the number of the added unit in the unit group.
51 public method addExistingUnitWithType takes unit existingUnit, real weight returns integer
52 local integer id = this.addExistingUnit(existingUnit)
53 call UnitPoolAddUnitType(this.m_unitPool, GetUnitTypeId(existingUnit), weight)
54 return id
55 endmethod
56
57 //removeExistingUnit
58
59 //methods
60
61 public method addUnitType takes integer unitTypeId, real weight returns nothing
62 call UnitPoolAddUnitType(this.m_unitPool, unitTypeId, weight)
63 endmethod
64
65 public method removeUnitType takes integer unitTypeId returns nothing
66 call UnitPoolRemoveUnitType(this.m_unitPool, unitTypeId)
67 endmethod
68
69 public method addItemType takes integer itemTypeId, real weight returns nothing
70 call ItemPoolAddItemType(this.m_itemPool, itemTypeId, weight)
71 endmethod
72
73 public method removeItemType takes integer itemTypeId returns nothing
74 call ItemPoolRemoveItemType(this.m_itemPool, itemTypeId)
75 endmethod
76
77 /// If you want to start a video and there are some spawn points near the scene you can disable them during the video.
78 public method enable takes nothing returns nothing
79 call EnableTrigger(this.m_deathTrigger)
80 if (TimerGetRemaining(this.m_spawnTimer) > 0.0) then
81 call PauseTimerBJ(false, this.m_spawnTimer)
82 endif
83 endmethod
84
85 public method disable takes nothing returns nothing
86 call DisableTrigger(this.m_deathTrigger)
87 if (TimerGetRemaining(this.m_spawnTimer) > 0.0) then
88 call PauseTimerBJ(true, this.m_spawnTimer)
89 endif
90 endmethod
91
92 public method spawn takes nothing returns nothing
93 local integer i
94 local real angle
95 local real range
96 local real x
97 local real y
98 local real facingAngle
99 local unit createdUnit
100 local effect createdEffect
101 debug if (this.m_unitPool == null) then
102 debug call this.print("Unit pool is null.")
103 debug return
104 debug endif
105 debug if (not IsUnitGroupDeadBJ(this.m_unitGroup)) then
106 debug call this.print("Unit group is not dead yet.")
107 debug endif
108 set i = 0
109 loop
110 exitwhen (i == this.m_count)
111 set angle = GetRandomReal(0.0, 360.0)
112 set range = GetRandomReal(0.0, this.m_range)
113 set x = GetPolarProjectionX(this.m_x, angle, range)
114 set y = GetPolarProjectionY(this.m_y, angle, range)
115 set facingAngle = GetRandomReal(0.0, 360.0)
116 set createdUnit = PlaceRandomUnit(this.m_unitPool, thistype.m_owner, x, y, facingAngle)
117 call GroupAddUnit(this.m_unitGroup, createdUnit)
118 set createdUnit = null
119 //Need global, faster?
120 if (thistype.m_effectPath != null) then
121 set createdEffect = AddSpecialEffect(thistype.m_effectPath, x, y)
122 call DestroyEffect(createdEffect)
123 set createdEffect = null
124 endif
125 set i = i + 1
126 endloop
127 endmethod
128
129 private method dropItem takes unit diedUnit returns nothing
130 local integer change
131 local item droppedItem
132 local player itemOwner
133 local integer i
134 local player user
135 if (this.m_itemPool != null) then
136 set change = GetRandomInt(0, 100)
137 if (change <= thistype.m_dropChance) then
138 set droppedItem = PlaceRandomItem(this.m_itemPool, GetUnitX(diedUnit), GetUnitY(diedUnit))
139 call SetItemDropID(droppedItem, GetUnitTypeId(diedUnit))
140 if (thistype.m_distributeItems) then
141 call thistype.distributeDroppedItem(droppedItem)
142 endif
143 set droppedItem = null
144 endif
145 endif
146 endmethod
147
148 private static method timerFunctionSpawn takes nothing returns nothing
149 local timer expiredTimer = GetExpiredTimer()
150 local ASpawnPoint this = AHashTable.global().handleInteger(expiredTimer, "this")
151 call this.spawn()
152 set expiredTimer = null
153 endmethod
154
155 private method startTimer takes nothing returns nothing
156 debug if (TimerGetRemaining(this.m_spawnTimer) > 0.0) then
157 debug call this.print("Timer has arleady been started.")
158 debug return
159 debug endif
160 call TimerStart(this.m_spawnTimer, thistype.m_time, false, function thistype.timerFunctionSpawn)
161 endmethod
162
163 private static method triggerConditionDeath takes nothing returns boolean
164 local trigger triggeringTrigger = GetTriggeringTrigger()
165 local unit triggerUnit = GetTriggerUnit()
166 local ASpawnPoint this = AHashTable.global().handleInteger(triggeringTrigger, "this")
167 local boolean result = IsUnitInGroup(triggerUnit, this.m_unitGroup)
168 set triggeringTrigger = null
169 set triggerUnit = null
170 return result
171 endmethod
172
173 private static method triggerActionDeath takes nothing returns nothing
174 local trigger triggeringTrigger = GetTriggeringTrigger()
175 local unit triggerUnit = GetTriggerUnit()
176 local thistype this = AHashTable.global().handleInteger(triggeringTrigger, "this")
177 call this.dropItem(triggerUnit)
178 if (IsUnitGroupDeadBJ(this.m_unitGroup)) then /// @todo maybe you should check it without ForGroup or this bj fucntion
179 call this.startTimer()
180 endif
181 set triggeringTrigger = null
182 set triggerUnit = null
183 endmethod
184
185 private method createDeathTrigger takes nothing returns nothing
186 local player user
187 local event triggerEvent
188 local conditionfunc conditionFunction
189 local triggercondition triggerCondition
190 local triggeraction triggerAction
191 set this.m_deathTrigger = CreateTrigger()
192 set user = Player(PLAYER_NEUTRAL_AGGRESSIVE)
193 set triggerEvent = TriggerRegisterPlayerUnitEvent(this.m_deathTrigger, user, EVENT_PLAYER_UNIT_DEATH, null)
194 set user = null
195 set conditionFunction = Condition(function thistype.triggerConditionDeath)
196 set triggerCondition = TriggerAddCondition(this.m_deathTrigger, conditionFunction)
197 set triggerAction = TriggerAddAction(this.m_deathTrigger, function thistype.triggerActionDeath)
198 call AHashTable.global().setHandleInteger(this.m_deathTrigger, "this", this)
199 set triggerEvent = null
200 set conditionFunction = null
201 set triggerCondition = null
202 set triggerAction = null
203 endmethod
204
205 private method createSpawnTimer takes nothing returns nothing
206 set this.m_spawnTimer = CreateTimer()
207 call AHashTable.global().setHandleInteger(this.m_spawnTimer, "this", this)
208 endmethod
209
210 public static method create takes real x, real y, real range returns thistype
211 local thistype this = thistype.allocate()
212 //start members
213 set this.m_x = x
214 set this.m_y = y
215 set this.m_range = range
216 //members
217 set this.m_unitPool = CreateUnitPool()
218 set this.m_itemPool = CreateItemPool()
219 set this.m_unitGroup = CreateGroup()
220
221 call this.createDeathTrigger()
222 call this.createSpawnTimer()
223 return this
224 endmethod
225
226 public static method createByExistingUnitWithType takes unit usedUnit, real weight, real x, real y, real range returns thistype
227 local thistype this = thistype.create(x, y, range)
228 call this.addExistingUnitWithType(usedUnit, weight)
229 return this
230 endmethod
231
232 public static method createByExistingUnitWithTypeAndRect takes unit usedUnit, real weight, rect usedRect, real range returns thistype
233 return thistype.createByExistingUnitWithType(usedUnit, weight, GetRectCenterX(usedRect), GetRectCenterY(usedRect), range)
234 endmethod
235
236 public static method createByExistingUnitWithTypeAndPosition takes unit usedUnit, real weight, real range returns thistype
237 local thistype this = thistype.create(GetUnitX(usedUnit), GetUnitY(usedUnit), range)
238 call this.addExistingUnitWithType(usedUnit, weight)
239 return this
240 endmethod
241
242 private method destroyDeathTrigger takes nothing returns nothing
243 call AHashTable.global().destroyTrigger(this.m_deathTrigger)
244 set this.m_deathTrigger = null
245 endmethod
246
247 private method destroySpawnTimer takes nothing returns nothing
248 call AHashTable.global().destroyTimer(this.m_spawnTimer)
249 set this.m_spawnTimer = null
250 endmethod
251
252 private static method removeUnit takes nothing returns nothing
253 local unit enumUnit = GetEnumUnit()
254 call RemoveUnit(enumUnit)
255 set enumUnit = null
256 endmethod
257
258 /// Removes all contained units.
259 public method onDestroy takes nothing returns nothing
260 //members
261 call DestroyUnitPool(this.m_unitPool)
262 set this.m_unitPool = null
263 call DestroyItemPool(this.m_itemPool)
264 set this.m_itemPool = null
265 call ForGroup(this.m_unitGroup, function thistype.removeUnit)
266 call DestroyGroup(this.m_unitGroup)
267 set this.m_unitGroup = null
268
269 call this.destroyDeathTrigger()
270 call this.destroySpawnTimer()
271 endmethod
272
273 /**
274 * Initializes the spawn point system. Please call this method before using anything of this system.
275 * @param time The time which has to elapse before the unit respawns.
276 * @param effectPath The path of the effect which is shown when the unit respawns. If this value is null there won't be shown any effect.
277 * @param dropChance The chance (percentaged) for dropping items.
278 * @param owner The player who owns all spawn point units.
279 */
280 public static method init takes real time, string effectPath, integer dropChance, boolean distributeItems, player owner, string textDistributeItem returns nothing
281 //static start members
282 set thistype.m_time = time
283 set thistype.m_effectPath = effectPath
284 set thistype.m_dropChance = dropChance
285 set thistype.m_distributeItems = distributeItems
286 set thistype.m_owner = owner
287 set thistype.m_textDistributeItem = textDistributeItem
288 //static members
289 set thistype.m_dropOwnerId = 0
290 endmethod
291
292 public static method distributeDroppedItem takes item usedItem returns nothing
293 local player itemOwner = thistype.getRandomItemOwner()
294 local player user
295 local integer i = 0
296 call SetItemPlayer(usedItem, itemOwner, true)
297 loop
298 exitwhen (i == bj_MAX_PLAYERS)
299 set user = Player(i)
300 if (IsPlayerPlayingUser(user)) then
301 call DisplayTimedTextToPlayer(user, 0.0, 0.0, 6.0, StringArg(StringArg(thistype.m_textDistributeItem, GetItemName(usedItem)), GetPlayerName(itemOwner)))
302 endif
303 set user = null
304 set i = i + 1
305 endloop
306 set itemOwner = null
307 endmethod
308
309 private static method getRandomItemOwner takes nothing returns player
310 local player user
311 local integer oldDropId = thistype.m_dropOwnerId
312 set thistype.m_dropOwnerId = thistype.m_dropOwnerId + 1
313 loop
314 if (thistype.m_dropOwnerId == bj_MAX_PLAYERS) then
315 set thistype.m_dropOwnerId = 0
316 endif
317 set user = Player(thistype.m_dropOwnerId)
318 if (IsPlayerPlayingUser(user) or thistype.m_dropOwnerId == oldDropId) then
319 return user
320 endif
321 set user = null
322 set thistype.m_dropOwnerId = thistype.m_dropOwnerId + 1
323 endloop
324 return user
325 endmethod
326 endstruct
327
328 endlibrary